home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / out.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  15KB  |  854 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    out.c
  12.  *
  13.  *   Revised: Dec 1988    Joe Montgomery
  14.  *
  15.  *   Revised out.c to use MOTOROLA assembly directives in order
  16.  *    to be compatible with C.Gibbs a68k assembler & blink
  17.  *    Added END statement
  18.  *    Changed .comm label,size to label DC.x 0
  19.  *
  20.  *     other modules:
  21.  *   Revised main.c to use Amiga File System Naming Conventions
  22.  *    Added ?,C,F switches. ? help
  23.  *                  C force data,bss into Chip memory
  24.  *                  F force data,bss into Fast memory
  25.  *   Revised d2.c so that externs are declared as XREF -----
  26.  *
  27.  *   Revised g2.c & gen.c to declare all called functions XREF
  28.  *     (will need to change this to declare only external functions)
  29.  *
  30.  *   All changes labeled JMM
  31.  *
  32.  *    Code generation output routines.
  33.  */
  34.  
  35. #include <stdio.h>
  36. #include "param.h"
  37. #include "nodes.h"
  38. #include "flags.h"
  39. #include "bstok.h"
  40. #include "tytok.h"
  41. #include "gen.h"
  42.  
  43.  
  44. #ifdef dLibs
  45. #include <ctype.h>
  46. #endif
  47.  
  48. #if MMCC
  49. overlay "pass2"
  50. #endif
  51.  
  52. #if CC68
  53. FILE *fopen();
  54. #endif
  55.  
  56. #if NEEDBUF
  57. char my_obuf[BUFSIZ];
  58. #endif
  59.  
  60. #define T_SEG    0
  61. #define D_SEG    1
  62. #define B_SEG    2
  63.  
  64. #define TO_TEXT to_seg(T_SEG)
  65. #define TO_DATA to_seg(D_SEG)
  66. #define TO_BSS    to_seg(B_SEG)
  67.  
  68. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  69.  
  70. extern FILE *output;
  71.  
  72.  
  73. /*JMM added -O switch to allow user to specify output file */
  74. char *outfilename,*errorfile;
  75. extern int nmerrors;
  76.  
  77. static int in_seg;
  78. static int lblnum;
  79. static int dat_size;
  80.  
  81. /* called to open output file. We've only just begun */
  82. out_start(s)
  83. char *s;
  84. {
  85.     char *scopy(), *outs;
  86.     register int len;
  87.  
  88. /* JMM added -O switch to allow user to specify output file */
  89.     if(outfilename) outs = scopy(outfilename);
  90.          else outs = scopy(s);
  91.     len = strlen(outs);
  92. /* JMM add -O switch */
  93.     if(outfilename){
  94.         output = fopen(outs,"w");
  95.         if(output == NULL )
  96.             fatals("Cant open",outs);
  97.     } else if ( len >= 2 && outs[len-2] == '.' &&
  98.             tolower(outs[len-1]) == 'c' ) {
  99.         outs[len-1] = 's';
  100.         output = fopen(outs, "w");
  101.         if (output == NULL)
  102.             fatals("Cant open", outs);
  103. #if NEEDBUF
  104.         setbuf(output, my_obuf);
  105. #endif
  106.     } else
  107.         output = stdout;
  108.     sfree(outs);
  109.  
  110.     in_seg = -1;
  111.     lblnum = 0;
  112.     dat_size = 0;
  113. }
  114.  
  115. /* closes output file.    All done */
  116. static char seterrorbuf[50];
  117. out_end()
  118. {
  119.     char *outs;
  120.     extern char *scopy();
  121.     FILE *err;
  122.  
  123.     fprintf(output, "\tEND \n");
  124.  
  125.     if (output != stdout)
  126.         fclose(output);
  127.     if( ( errorfile != NULL) ){
  128.         outs = scopy((char *) errorfile );
  129.         err = fopen(outs,"w");
  130.         if(err == NULL )
  131.             fatals("Cant open",outs);
  132.         fprintf(err,"%d",nmerrors);
  133.         close(err);
  134.         sfree(outs);
  135.     }
  136. }
  137.  
  138. /* Assembler segment Directives */
  139. static char *sg_go[] = {
  140.     "CODE CODE",   /* .text  segment  ?same as code segment? */
  141.     "DATA DATA",   /* .data  segment */
  142.     "BSS BSS"     /* .bss  segment */
  143. };
  144. /* JMM added ability to force Data,BSS into either Chip or Fast */
  145. short usefastmemory,usechipmemory;
  146.  
  147. static char *chipsg_go[] = {
  148.     "CODE CODE",   /* .text  segment  ?same as code segment? */
  149.     "DATA CHIPDATA CHIP",   /* .data  segment */
  150.     "BSS CHIPBSS CHIP"     /* .bss  segment */
  151. };
  152.  
  153. static char *fastsg_go[] = {
  154.     "CODE CODE",   /* .text  segment  ?same as code segment? */
  155.     "DATA FASTDATA FAST",   /* .data  segment */
  156.     "BSS FASTBSS FAST"     /* .bss  segment */
  157. };
  158.  
  159. /* extern directive, global directive */
  160. char externdir[]="\tXREF \t";
  161. char globaldir[]="\tXDEF \t";
  162. char externfuncdir[]="\tXREF \t";
  163.  
  164. to_text()
  165. {
  166.     TO_TEXT;   /* to_seg(0) *//* fprintf(output,"   .text ") */
  167. }
  168.  
  169. to_seg(sg)
  170. {
  171. char *segment;
  172. /* JMM modified to_seg to force data,bss into either CHIP or FAST */
  173.     if (sg == in_seg)
  174.         return;
  175.     if(usechipmemory)segment =(char *) chipsg_go[sg];
  176.        else if(usefastmemory) segment = (char *)fastsg_go[sg];
  177.        else segment =(char *) sg_go[sg];
  178.     fprintf(output, "\t%s\n", segment);
  179.     in_seg = sg;
  180. }
  181.  
  182. /* JMM ? output a long ? */
  183. o_aln(x)
  184. {
  185.     if (x && (dat_size & 1)) {
  186.         dat_size++;
  187.         TO_DATA;      /* data segment */
  188.         fprintf(output, "\tCNOP 0,2\n");/* was .even */
  189.     }
  190. }
  191.  
  192. char *rnms[] = {
  193.     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  194.     "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
  195. };
  196.  
  197. /* return string containing register name */
  198. char *regnm(n)
  199. {
  200.     return rnms[n];
  201. }
  202.  
  203. /*     define constant of length n */
  204. char *
  205. init_str(n)
  206. int n;
  207. {
  208.     char *s;
  209.  
  210.     switch (n) {
  211.     case 1:
  212.         s = "DC.B";    break;
  213.     case 2:
  214.         s = "DC.W";    break;
  215.     default:
  216.         s = "DC.L";    break;
  217.     }
  218.     return s;
  219. }
  220.  
  221.  
  222. tlen(n)
  223. {
  224.     switch (n) {
  225.     case 1:
  226.         return 'b';
  227.     case 2:
  228.         return 'w';
  229.     default:
  230.         return 'l';
  231.     }
  232. }
  233.  
  234. /* JMM ? output  init node pointer         *
  235.  *   output predefined values for variable ? */
  236. o_vinit(tp, xp)
  237. NODEP tp, xp;         /* Node pointers */
  238. {
  239.  /*  .dc.b   t_size 1
  240.   *  .dc.w        2
  241.   *  .dc.l        3 or greater
  242.   */
  243.     fprintf(output, "\t%s\t", init_str((int)tp->t_size));
  244.     dat_size += tp->t_size;
  245.  
  246.     p2_expr(&xp);
  247.     asn_chk(tp, xp);
  248.     to_init(xp, tp);
  249.  
  250.     fputc('\n', output);
  251. }
  252.  
  253.  
  254. to_init(np, typ)
  255. NODEP np, typ;
  256. {
  257.     NODEP tp;
  258.  
  259.     tp = allocnode();
  260.     tp->e_token = TCONV;
  261.     tp->n_tptr = typ;
  262.     tp->n_flags |= N_COPYT;
  263.     tp->n_left = np;
  264.     tp->e_type = E_UNARY;
  265.     strcpy(tp->n_name, "i cast");
  266.  
  267.     genx(tp, FORINIT);
  268. }
  269.  
  270. /* output move.x  #(a6),rn    where x=b,w,l , rn=a0-a7 or d0-d7*/
  271. out_argreg(np)
  272. NODEP np;
  273. {
  274.     fprintf(output, "\tmove.%c\t%d(a6),%s\n",
  275.         tlen((int)np->n_tptr->t_size), (int)np->e_offs,
  276.         regnm(np->e_rno));
  277. }
  278.  
  279.  
  280. extern    int    pflag;
  281.  
  282. /* JMM ? output label ? makes function labels etc */
  283. out_fstart(np)
  284. NODEP np;
  285. {
  286.     TO_TEXT; /* code segment */
  287.     if (np->e_sc != K_STATIC) {
  288. /* JMM changed to output XDEF name */
  289.         fprintf(output, globaldir);
  290.         und_nnm(np); /* output _XXXXX  where XXXXX is name of variable */
  291.         fputc('\n', output);
  292.     }
  293.     und_nnm(np);
  294.     fprintf(output, ":\n");
  295.  
  296.     if (pflag) {
  297.         int    tlab = new_lbl();
  298.  
  299.         TO_BSS;
  300.         fprintf(output, "L%d:\tDS.L\t1\n", tlab);
  301.         TO_TEXT;
  302.         fprintf(output, "\tmove.l\t#");
  303.         und_nnm(np);
  304.         fprintf(output, ",a0\n");
  305.  
  306.         fprintf(output, "\tmove.l\t#L%d,a1\n", tlab);
  307.         fprintf(output,"\tXREF \tmcount\n");
  308.         fprintf(output,"; Calling profiler \n");
  309.         fprintf(output, "\tjsr\tmcount\n");
  310.     }
  311. }
  312.  
  313. static char rbuf[30];
  314.  
  315. char *
  316. regstr(regs)
  317. {
  318.     int lod, hid, loa, hia;
  319.     register i;
  320.     char *bp = rbuf;
  321.  
  322.     lod = 999;
  323.     hid = -1;
  324.     for (i=DRV_START; i<=DRV_END; i++)
  325.         if (regs & (1<<i)) {
  326.             if (i < lod)  lod = i;
  327.             if (i > hid)  hid = i;
  328.         }
  329.     loa = 999;
  330.     hia = -1;
  331.     for (i=ARV_START; i<=ARV_END; i++)
  332.         if (regs & (1<<i)) {
  333.             if (i < loa)  loa = i;
  334.             if (i > hia)  hia = i;
  335.         }
  336.     if (lod < 999) {
  337.         if (lod != hid)
  338.             sprintf(bp, "d%d-d%d", lod, hid);
  339.         else
  340.             sprintf(bp, "d%d", lod);
  341.         if (loa < 999) {
  342.             bp += strlen(rbuf);
  343.             *bp++ = '/';
  344.         }
  345.     }
  346.     if (loa < 999) {
  347.         if (loa != hia)
  348.             sprintf(bp, "a%d-a%d", loa-AREG, hia-AREG);
  349.         else
  350.             sprintf(bp, "a%d", loa-AREG);
  351.     }
  352.     return rbuf;
  353. }
  354.  
  355. out_fend(regs, lsize)
  356. long lsize;
  357. {
  358.     if (lsize < 0x7fff)
  359.         fprintf(output, "\tlink\ta6,#-%d\n", (int)lsize);
  360.     else
  361.         fprintf(output, "\tlink\ta6,#0\n\tsub.l\t#%ld,sp\n",
  362.             lsize);
  363.     if (regs)
  364.         fprintf(output, "\tmovem.l\t%s,-(sp)\n", regstr(regs));
  365. }
  366.  
  367. out_fret(regs, strl)
  368. {
  369.     if (regs)
  370.         fprintf(output, "\tmovem.l\t(sp)+,%s\n", regstr(regs));
  371.     if (strl)
  372.         fprintf(output, "\tmove.l\t#L%d,a0\n", strl);
  373.     fprintf(output, "\tunlk\ta6\n\trts\n");
  374. }
  375.  
  376. out_fs(strl, size)
  377. long size;
  378. {
  379.     TO_BSS;
  380.     def_lbl(strl);
  381.     fprintf(output, "\tDS.W \t%ld\n", size/2);
  382. }
  383.  
  384. /* ? output global variables ? */
  385. out_gv(np, isbss)
  386. register NODEP np;
  387. {
  388.     long sz;
  389.     char c;
  390.  
  391.     if (np->e_sc == K_STATIC) {
  392.         np->e_offs = lblnum++;
  393.     }
  394.      /* JMM ? added part to print out XREF statement for a68k ? */
  395.     if (np->e_sc == K_EXTERN) {
  396.         to_seg(isbss ? B_SEG : D_SEG);
  397.         /*if (np->e_sc != K_STATIC) { */
  398.             fprintf(output, externdir);
  399.             out_nm(np);
  400.             fputc('\n', output);
  401.           /*  }                */
  402.     }
  403.     if (np->e_sc != K_EXTERN) {
  404.         to_seg(isbss ? B_SEG : D_SEG);
  405.         if (np->e_sc != K_STATIC) {
  406.             fprintf(output, globaldir);
  407.             out_nm(np);
  408.             fputc('\n', output);
  409.         }
  410.         if (isbss) {
  411.             if (np->e_sc == K_STATIC) {
  412.                 out_nm(np);
  413.                 sz = np->n_tptr->t_size;
  414.                 c = 'b';
  415.                 if (np->n_tptr->t_aln) {
  416.                     c = 'w';
  417.                     sz /= 2;
  418.                 }
  419.                 fprintf(output, ":\tDS.%c\t%ld\n", c, sz);
  420.             } else {
  421.                 out_nm(np);
  422.                 sz = np->n_tptr->t_size;
  423.                 if (sz & 1) sz++;  /* ALCYON hack */
  424.                 fprintf(output, ":\t DS.%c 0 \n", tlen(sz) );
  425.                 sz -= 4;
  426.                 while (sz > 0){
  427.                   fprintf(output,"\t DS.W 0\n");
  428.                   sz -= 2;
  429.                 }
  430.  
  431.  
  432. /*                  fprintf(output, "\t.comm\t");
  433.  *                 out_nm(np);
  434.  *                 sz = np->n_tptr->t_size;
  435.  *                 if (sz & 1) sz++;  /* ALCYON hack *  /
  436.  *                 fprintf(output, ",%ld\n", sz);
  437.  */
  438.             }
  439.         } else {
  440.             out_nm(np);
  441.             fprintf(output, ":\n");
  442.         }
  443.     }
  444. }
  445.  
  446. new_lbl()
  447. {
  448.     return lblnum++;
  449. }
  450.  
  451. def_lbl(l)
  452. {
  453.     fprintf(output, "L%d:\n", l);
  454. }
  455.  
  456. out_br(l)
  457. {
  458.     if (l < 0)
  459.         error("bad branch");
  460.     else
  461.         fprintf(output, "\tbra\tL%d\n", l);
  462. }
  463.  
  464. static char *bnm[] = {
  465.     "",
  466.     "beq",
  467.     "bne",
  468.     "blt",
  469.     "bge",
  470.     "ble",
  471.     "bgt",
  472.     "bra",
  473.     "nop",
  474.     "bcs",
  475.     "bcc",
  476.     "bls",
  477.     "bhi"
  478. };
  479.  
  480. out_b(key, l)
  481. {
  482.     if (key != B_NO)
  483.         fprintf(output, "\t%s\tL%d\n", bnm[key], l);
  484. }
  485.  
  486. out_bnol(key)
  487. {
  488.     fprintf(output, "\t%s\t", bnm[key]);
  489. }
  490.  
  491. out_d0cmp(x)
  492. {
  493.     fprintf(output, "\tcmp.w\t#%d,d0\n", x);
  494. }
  495.  
  496. out_d0sub(x)
  497. {
  498.     fprintf(output, "\tsub.w\t#%d,d0\n", x);
  499. }
  500.  
  501. out_tlbl(l)
  502. {
  503.     fprintf(output, "\tDC.L\tL%d\n", l);
  504. }
  505.  
  506. out_tsw()
  507. {
  508.     fprintf(output, "\text.l\td0\n");
  509.     fprintf(output, "\tasl.l\t#2,d0\n");
  510.     fprintf(output, "\tmove.l\t4(pc,d0.l),a0\n");
  511.     fprintf(output, "\tjmp\t(a0)\n");
  512. }
  513.  
  514. out_nm(np)
  515. NODEP np;
  516. {
  517.     if (np->e_sc == K_STATIC)
  518.         fprintf(output, "L%d", (int)np->e_offs);
  519.     else
  520.         und_nnm(np);
  521. }
  522.  
  523. externfuncref(np)
  524. NODEP np;
  525. {
  526.     if (  np->e_sc != K_STATIC){
  527.         fprintf(output, externfuncdir);
  528.         fput_nnm(np->n_left);
  529.         fprintf(output,"\n");
  530.     }
  531. }
  532.  
  533.  
  534. out_zi(tp)
  535. NODEP tp;
  536. {
  537.     char *s;
  538. /*
  539.     switch (tp->t_token) {
  540.     case K_FLOAT:
  541.         fprintf(output, "\t.float\t0.0\n");     return;
  542.     case K_DOUBLE:
  543.         fprintf(output, "\t.double\t0.0\n");    return;
  544.     }
  545. */
  546.     dat_size += tp->t_size;
  547.     s = init_str((int)tp->t_size);
  548.     fprintf(output, "\t%s\t0\n", s);
  549. }
  550.  
  551. o_nz(sz, aln)
  552. long sz;
  553. {
  554.     dat_size += sz;
  555.     if (aln) {
  556.         if (sz & 1)
  557.             fprintf(output, "\tDS.B\t1\n");
  558.         sz >>= 1;
  559.         fprintf(output, "\tDS.W\t%ld\n", sz);
  560.     } else {
  561.         fprintf(output, "\tDS.B\t%ld\n", sz);
  562.     }
  563. }
  564.  
  565. dumpstrs(np)
  566. NODEP np;
  567. {
  568.     TO_DATA;
  569. more:
  570.     if (np == NULL)
  571.         return;
  572.     fprintf(output, "L%d:", (int)np->g_offs);
  573.     out_scon(np);
  574.     np = np->n_next;
  575.     goto more;
  576. }
  577.  
  578. int see_esc;
  579.  
  580. out_scon(np)
  581. NODEP np;
  582. {
  583.     int len = 0;
  584.  
  585.     if (np == NULL)
  586.         return 0;
  587.     see_esc = 0;
  588. more:
  589.     if (np->n_name[0]) {
  590.         fprintf(output, "\tDC.B\t");
  591.         len += out_str(np->n_name);
  592.         putc('\n', output);
  593.     }
  594.     np = np->n_nmx;
  595.     if (np)
  596.         goto more;
  597.  
  598.     fprintf(output, "\tDC.B\t0\n");
  599.     len++;
  600.     dat_size += len;
  601.     return len;
  602. }
  603.  
  604. out_str(s)
  605. char *s;
  606. {
  607.     int len;
  608.     register c;
  609.  
  610.     len = 0;
  611.     for ( ; c = *s; s++) {
  612.         if (see_esc) {  /* allow null */
  613.             c--;
  614.             see_esc = 0;
  615.         } else if (c == 1) {
  616.             see_esc = 1;
  617.             continue;
  618.         }
  619.         if (len)
  620.             putc(',', output);
  621.         out_1c(c);
  622.         len++;
  623.     }
  624.     return len;
  625. }
  626.  
  627. out_asm(np)
  628. NODEP np;
  629. {
  630.     putc('\t', output);
  631. more:
  632.     fprintf(output, "%s", np->n_name);      /* no \0 or \1 please! */
  633.     np = np->n_nmx;
  634.     if (np)
  635.         goto more;
  636.     putc('\n', output);
  637. }
  638.  
  639.  
  640. /* Output  underscore name */
  641. und_nnm(np)
  642. NODEP np;
  643. {
  644.     fputc('_', output);
  645.     fput_nnm(np);
  646. }
  647.  
  648. out_1c(c)
  649. char c;
  650. {
  651.     fprintf(output, "$%x", c & 0xff);
  652. }
  653.  
  654. outcode(np)
  655. register NODEP np;
  656. {
  657.     NODEP tp;
  658.  
  659.     if (np == NULL) return;
  660.  
  661.     switch (np->g_type) {
  662.     case EV_NONE:
  663.         break;
  664.     case EV_RL:
  665.         outcode(np->n_right);
  666.         outsub(np->g_betw, np);
  667.         /* fall through */
  668.     case EV_LEFT:
  669.         outcode(np->n_left);
  670.         break;
  671.     case EV_LR:
  672.     case EV_LRSEP:
  673.         outcode(np->n_left);
  674.         outsub(np->g_betw, np);
  675.         /* fall through */
  676.     case EV_RIGHT:
  677.         outcode(np->n_right);
  678.         break;
  679.     default:
  680.         printf("bad eval %d ", np->g_type);
  681.     }
  682.     if (np->n_flags & N_COPYT)      /* g_code is a char * */
  683.         outsub(np->g_code, np);
  684.     else                /* g_code is a list of nodes */
  685.         for (tp=np->g_code; tp != NULL; tp = tp->g_code)
  686.             outsub(tp->n_name, np);
  687. }
  688.  
  689. outsub(cp, np)
  690. register char *cp;
  691. register NODEP np;
  692. {
  693.     register char c;
  694.  
  695.     if (cp == NULL) return;
  696.     while (c = *cp++)
  697.         if (c == '<')
  698.             out_let(*cp++, np->n_left);
  699.         else if (c == '>')
  700.             out_let(*cp++, np->n_right);
  701.         else if (c == '\'') {
  702.             c = *cp++;
  703.             fputc(c, output);
  704.         } else if (c == 'L')
  705.             seelab(*cp++, np);
  706.         else if (c == 'R')
  707.             seereg(np, *cp++);
  708.         else if (c >= 'A' && c <= 'Z') {
  709.             out_let(c, np);
  710.         } else
  711.             fputc(c, output);
  712. }
  713.  
  714. seereg(np, c)
  715. NODEP np;
  716. {
  717.     int i;
  718.  
  719.     switch (c) {
  720.     case '0':       i = np->g_rno;  break;
  721.     case '1':       i = np->g_r1;   break;
  722.     case '2':       i = np->g_r2;   break;
  723.     }
  724.     fprintf(output, regnm(i));
  725. }
  726.  
  727. out_let(c, np)
  728. register NODEP np;
  729. {
  730.     int i;
  731.  
  732.     switch (c) {
  733.     case 'A':
  734.         if (np->g_flags & IMMEDID)
  735.             fputc('#', output);
  736.         out_a(np, output);
  737.         break;
  738.     case 'F':       /* branch if false */
  739.         i = cctok(np);
  740.         i = (i&1) ? i+1 : i-1;  /* reverse truth */
  741.         out_bnol(i);
  742.         break;
  743.     case 'K':
  744.         fprintf(output, "%ld", np->g_bsize);
  745.         break;
  746.     case 'N':
  747.         fprintf(output, "%s", np->n_name);
  748.         break;
  749.     case 'O':
  750.         fprintf(output, "%ld", np->g_offs);
  751.         break;
  752.     case 'Q':
  753.         if (np->g_flags & IMMEDID) {
  754.             warn("constant test expr");
  755.             if (np->g_token == ICON && np->g_offs == 0)
  756.                 fprintf(output, "\tor\t#$FF,ccr\n");
  757.             else
  758.                 fprintf(output, "\tand\t#0,ccr\n");
  759.             return;
  760.         }
  761.         fprintf(output, "\t%s.%c\t", isareg(np) ? "cmp" : "tst",
  762.             tlen(np->g_sz));
  763.         if (isareg(np))
  764.             fprintf(output, "#0,");
  765.         out_let('A', np);
  766.         fputc('\n', output);
  767.         break;
  768.     case 'S':
  769.         fputc(tlen(np->g_sz), output);
  770.         break;
  771.     case 'T':       /* branch if true */
  772.         out_bnol(cctok(np));
  773.         break;
  774.     case 'U':
  775.         fputc(np->g_ty == ET_U ? 'u' : 's', output);
  776.         break;
  777.     case 'W':       /* field width 1's */
  778.         fprintf(output, "$%x", ones(np->g_fldw));
  779.         break;
  780.     case 'X':       /* ~(W << offset) */
  781.         fprintf(output, "$%x", ~(ones(np->g_fldw)<<np->g_fldo));
  782.         break;
  783.     case 'Y':       /* field offset */
  784.         fprintf(output, "%d", np->g_fldo);
  785.         break;
  786.     case 'Z':       /* field offset - 8 */
  787.         fprintf(output, "%d", np->g_fldo - 8);
  788.         break;
  789.     default:
  790.         printf("bad out_let %c ", c);
  791.     }
  792. }
  793.  
  794. out_a(np, fd)
  795. register NODEP np;
  796. FILE *fd;
  797. {
  798.     int offs = np->g_offs;
  799.  
  800.     switch (np->g_token) {
  801.     case ICON:
  802.         fprintf(fd, "%ld", np->g_offs);
  803.         break;
  804.     case FCON:
  805.         /* works for ALCYON C */
  806.         /* otherwise depends on floating internal format */
  807.         fprintf(fd, "$%lx", np->g_offs);
  808.         break;
  809.     case ONAME:
  810.         while (np->g_flags & (CHILDNM|RCHILDNM)) {
  811.             np = (np->g_flags & CHILDNM) ?
  812.                 np->n_left : np->n_right;
  813.         }
  814.         qput_nnm(np, fd);
  815.         if (offs)
  816.             fprintf(fd, offs > 0 ? "+%d" : "%d", offs);
  817.         break;
  818.     case PUSHER:
  819.         fprintf(fd, "(sp)+");
  820.         break;
  821.     case OREG:
  822.         if (offs)
  823.             fprintf(fd, "%d", offs);
  824.         fprintf(fd, "(%s)", regnm(np->g_rno));
  825.         break;
  826.     case REGVAR:
  827.         fprintf(fd, regnm(np->g_rno));
  828.         break;
  829.     case ',':
  830.         fputc(',', fd);         /* for debug */
  831.         break;
  832.     default:
  833.         if (np->g_token >= BR_TOK) {
  834.             fprintf(fd, "B_%s", bnm[np->g_token - BR_TOK]);
  835.             break;
  836.         }
  837.         printf("? tok %d ", np->g_token);
  838.     }
  839. }
  840.  
  841. seelab(c, np)
  842. char c;
  843. NODEP np;
  844. {
  845.     c -= '1';
  846.     fprintf(output, "L%d", (int)np->g_bsize+c);
  847. }
  848.  
  849. ones(n)
  850. {
  851.     return (1 << n) - 1;
  852. }
  853.  
  854.